package co.yixiang.yshop.module.crm.controller.admin.crmclues;

import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.Operation;

import jakarta.validation.constraints.*;
import jakarta.validation.*;
import jakarta.servlet.http.*;
import java.util.*;
import java.util.stream.Collectors;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import cn.hutool.core.util.StrUtil;
import org.springframework.web.multipart.MultipartFile;

import co.yixiang.yshop.framework.common.pojo.PageParam;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.framework.common.pojo.CommonResult;
import co.yixiang.yshop.framework.common.util.object.BeanUtils;
import co.yixiang.yshop.framework.ip.core.utils.AreaUtils;
import co.yixiang.yshop.framework.ip.core.Area;
import co.yixiang.yshop.framework.redis.util.redis.RedisUtil;
import static co.yixiang.yshop.framework.common.pojo.CommonResult.success;

import co.yixiang.yshop.framework.excel.core.util.ExcelUtils;

import co.yixiang.yshop.framework.apilog.core.annotation.ApiAccessLog;
import static co.yixiang.yshop.framework.apilog.core.enums.OperateTypeEnum.*;

import co.yixiang.yshop.module.crm.controller.admin.crmclues.vo.*;
import co.yixiang.yshop.module.crm.controller.admin.crmcustomer.vo.*;
import co.yixiang.yshop.module.crm.dal.dataobject.crmclues.CrmCluesDO;
import co.yixiang.yshop.module.crm.service.crmclues.CrmCluesService;
import co.yixiang.yshop.module.system.dal.dataobject.user.AdminUserDO;
import co.yixiang.yshop.module.system.dal.mysql.user.AdminUserMapper;
import co.yixiang.yshop.module.crm.enums.CustomerTypesEnum;
import co.yixiang.yshop.module.crm.util.DynamicExcelExportUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

@Tag(name = "管理后台 - 线索")
@RestController
@RequestMapping("/crm/clues")
@Validated
public class CrmCluesController {

    @Resource
    private CrmCluesService cluesService;

    @Resource
    private AdminUserMapper userMapper;

    @PostMapping("/create")
    @Operation(summary = "创建线索")
    @PreAuthorize("@ss.hasPermission('crm:clues:create')")
    public CommonResult<Long> createClues(@Valid @RequestBody CrmCluesSaveReqVO createReqVO) {
        return success(cluesService.createClues(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新线索")
    @PreAuthorize("@ss.hasPermission('crm:clues:update')")
    public CommonResult<Boolean> updateClues(@Valid @RequestBody CrmCluesSaveReqVO updateReqVO) {
        cluesService.updateClues(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除线索")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('crm:clues:delete')")
    public CommonResult<Boolean> deleteClues(@RequestParam("id") Long id) {
        cluesService.deleteClues(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得线索")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('crm:clues:query')")
    public CommonResult<CrmCluesRespVO> getClues(@RequestParam("id") Long id) {
        CrmCluesDO clues = cluesService.getClues(id);
        return success(BeanUtils.toBean(clues, CrmCluesRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得线索分页")
    @PreAuthorize("@ss.hasPermission('crm:clues:query')")
    public CommonResult<PageResult<CrmCluesRespVO>> getCluesPage(@Valid CrmCluesPageReqVO pageReqVO) {
        return success(cluesService.getCluesPage(pageReqVO));
    }

    @GetMapping("/open")
    @Operation(summary = "放入线索池")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('crm:clues:query')")
    public CommonResult<Boolean> openClues(@RequestParam("id") Long id) {
        cluesService.openClues(id);
        return success(true);
    }

    @GetMapping("/receive")
    @Operation(summary = "领取线索")
    @Parameter(name = "id", description = "编号", required = true)
    public CommonResult<Boolean> receiveCustomer(@RequestParam("id") Long id) {
        cluesService.receiveClues(id);
        return success(true);
    }

    @PostMapping("/createCustomer")
    @Operation(summary = "转换客户")
    @PreAuthorize("@ss.hasPermission('crm:clues:to-customer')")
    public CommonResult<Boolean> createCustomer(@Valid @RequestBody CrmCustomerSaveReqVO createReqVO) {
        cluesService.createCustomer(createReqVO);
        return success(true);
    }

    @GetMapping("/get-import-template")
    @Operation(summary = "获得导入模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 创建模板示例，包含提示信息行并与图片格式一致
        // 手动创建导出 demo
        List<CrmCluesImportVO> list = Arrays.asList(
                CrmCluesImportVO.builder().channelSource("B站").name("张三").telephone("19188888886").wechat("").sex("男")
                        .age("19").detailAddress("广东省/深圳市").married("未婚").education("本科")
                        .height(178.0).weight(68.0).income("5000及以下").remarks("老家海南着急结婚").build(),
                CrmCluesImportVO.builder().channelSource("微信公众号").name("李四").telephone("18500000038").wechat("").sex("男")
                        .age("28").detailAddress("北京/北京市").married("未婚").education("硕士")
                        .height(180.0).weight(70.0).income("50000以上").remarks("北京本地只想找北京的女生").build(),
                CrmCluesImportVO.builder().channelSource("广点通").name("王五").telephone("17322222240").wechat("").sex("男")
                        .age("29").detailAddress("上海市/上海市").married("未婚").education("本科")
                        .height(175.0).weight(65.0).income("5001-8000").remarks("").build(),
                CrmCluesImportVO.builder().channelSource("广点通").name("赵六").telephone("15711111739").wechat("").sex("女")
                        .age("30").detailAddress("上海市/上海市").married("未婚").education("本科")
                        .height(165.0).weight(50.0).income("12001-20000").remarks("家里催婚想找上海本地的").build()
        );

        // 使用EasyExcel API导出带提示信息的模板
        // 设置响应头
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String encodedFileName = URLEncoder.encode("线索导入模板.xls", StandardCharsets.UTF_8.name())
                .replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName);

        // 添加提示信息和示例数据
        // 注意：这里直接使用ExcelUtils进行输出，因为不支持添加提示行
        // 所以在实际使用时，需要告知用户在模板第一行添加提示信息，第二行是表头，从第三行开始填写数据
        ExcelUtils.write(response, "线索导入模板.xls", "线索列表", CrmCluesImportVO.class, list);
    }

    @PostMapping("/import")
    @Operation(summary = "导入用户")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "deptId", description = "部门ID"),
            @Parameter(name = "adminIds", description = "用户ID 多个逗号隔开"),
            @Parameter(name = "averageType", description = "分配方式")
    })
    public CommonResult<CustomerImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                          @RequestParam("deptId") String deptId,
                                                          @RequestParam("adminIds") String adminIds,
                                                          @RequestParam("averageType") Integer averageType) throws Exception {
        // 根据图片所示，Excel文件的第1行是提示信息，第2行是表头，所以数据从第3行开始
        // headRowNumber=2表示表头在第2行，数据从第3行开始
        List<CrmCluesImportVO> list = ExcelUtils.read(file, CrmCluesImportVO.class, 2);

        // 过滤掉所有字段都为空的行
        list = list.stream()
                .filter(vo -> isNotEmptyRow(vo))
                .collect(Collectors.toList());

        // 调试信息，打印过滤后的数据
        System.out.println("过滤后的数据总数: " + list.size());
        for (int i = 0; i < Math.min(list.size(), 5); i++) {
            System.out.println("第" + (i+1) + "行数据: " + list.get(i));
        }

        return success(cluesService.importList(list, deptId, adminIds, averageType));
    }

    /**
     * 判断一行数据是否为空行（所有字段都为null或空字符串）
     *
     * @param vo 导入的数据对象
     * @return 如果不是空行返回true，否则返回false
     */
    private boolean isNotEmptyRow(CrmCluesImportVO vo) {
        if (vo == null) {
            return false;
        }

        // 检查字符串类型字段
        boolean hasNonEmptyStringField =
            isNotEmpty(vo.getChannelSource()) ||
            isNotEmpty(vo.getName()) ||
            isNotEmpty(vo.getTelephone()) ||
            isNotEmpty(vo.getWechat()) ||
            isNotEmpty(vo.getSex()) ||
            isNotEmpty(vo.getAge()) ||
            isNotEmpty(vo.getDetailAddress()) ||
            isNotEmpty(vo.getMarried()) ||
            isNotEmpty(vo.getEducation()) ||
            isNotEmpty(vo.getIncome()) ||
            isNotEmpty(vo.getRemarks());

        // 检查数值类型字段
        boolean hasNonNullNumericField =
            vo.getHeight() != null ||
            vo.getWeight() != null;

        return hasNonEmptyStringField || hasNonNullNumericField;
    }

    /**
     * 判断字符串是否非空
     *
     * @param str 字符串
     * @return 如果字符串非空返回true，否则返回false
     */
    private boolean isNotEmpty(String str) {
        return str != null && !str.trim().isEmpty();
    }

    @PostMapping("/transfer")
    @Operation(summary = "转移线索")
    public CommonResult<Boolean> transferCustomer(@Valid @RequestBody CrmCluesTransferVO transferVO) {
        cluesService.transfer(transferVO);
        return success(true);
    }

    @PostMapping("/transfer-to-bill")
    @Operation(summary = "线索转账单", description = "将线索转换为账单，支持添加充值金额，自动计算余额(充值金额-花费)和单价(花费/注册数)")
    @PreAuthorize("@ss.hasPermission('crm:clues:to-bill')")
    public CommonResult<Long> transferToBill(@Valid @RequestBody CrmCluesBillTransferVO transferVO) {
        return success(cluesService.transferToBill(transferVO));
    }

    @PostMapping("/saveRedisSet")
    @Operation(summary = "线索公海规则配置")
    public CommonResult<Boolean> saveRedisSet(@Valid @RequestBody CluesConfigSetVO configSetVO) {
        RedisUtil.set("cluesNum", configSetVO.getCluesNum());
        RedisUtil.set("cluesNotRecordDay", configSetVO.getNotRecordDay());
        RedisUtil.set("cluesNotSuccessDay", configSetVO.getNotSuccessDay());
        return success(true);
    }

    @GetMapping("/getRedisSet")
    @Operation(summary = "获得线索公海规则配置")
    public CommonResult<CluesConfigSetVO> getRedisSet() {
        CluesConfigSetVO configSetVO = CluesConfigSetVO.builder()
                .cluesNum(RedisUtil.get("cluesNum"))
                .notRecordDay(RedisUtil.get("cluesNotRecordDay"))
                .notSuccessDay(RedisUtil.get("cluesNotSuccessDay"))
                .build();
        return success(configSetVO);
    }


    @PostMapping("/import-legacy")
    @Operation(summary = "导入数据", description = "导入旧格式的Excel数据")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "deptId", description = "部门ID"),
            @Parameter(name = "adminIds", description = "用户ID 多个逗号隔开"),
            @Parameter(name = "averageType", description = "分配方式")
    })
    @PreAuthorize("@ss.hasPermission('crm:clues:import')")
    public CommonResult<CustomerImportRespVO> importLegacyExcel(@RequestParam("file") MultipartFile file,
                                                          @RequestParam("deptId") String deptId,
                                                          @RequestParam("adminIds") String adminIds,
                                                          @RequestParam("averageType") Integer averageType) throws Exception {
        // 从第二行开始读取数据，跳过提示行，第二行是表头
        List<CrmCluesImportVO> list = ExcelUtils.read(file, CrmCluesImportVO.class, 2);

        // 过滤掉所有字段都为空的行
        list = list.stream()
                .filter(vo -> isNotEmptyRow(vo))
                .collect(Collectors.toList());

        return success(cluesService.importLegacyList(list, deptId, adminIds, averageType));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出线索 Excel")
    @PreAuthorize("@ss.hasPermission('crm:clues:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportCluesExcel(@Valid CrmCluesPageReqVO pageReqVO,
            HttpServletResponse response) throws IOException {
        // 使用无限大小的分页
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);

        // 详细的调试日志 - 打印完整的请求参数
        System.out.println("线索导出查询参数: " + pageReqVO.toString());

        // 获取数据 - 直接调用 getCluesPage 方法
        // 该方法会根据 ownerUserIds 参数自动使用导出查询逻辑
        PageResult<CrmCluesRespVO> pageResult = cluesService.getCluesPage(pageReqVO);
        List<CrmCluesRespVO> list = pageResult.getList();

        // 记录返回的结果数量
        System.out.println("查询到符合条件的线索数量: " + list.size());

        // 预处理数据
        for (CrmCluesRespVO vo : list) {
            // 1. 设置区域信息 - 先检查城市编码
            try {
                // 先检查城市编码是否存在且不为0
                if (vo.getCity() != null && vo.getCity() != 0) {
                    // 城市编码存在且不为0，获取城市地区对象
                    Area city = AreaUtils.getArea(vo.getCity());
                    if (city != null) {
                        // 获取父级地区（省份）
                        Area parent = city.getParent();
                        StringBuilder sb = new StringBuilder();

                        // 先展示父级名称（省份）
                        if (parent != null) {
                            sb.append(parent.getName());
                            sb.append(" ");
                        }

                        // 再展示城市名称
                        sb.append(city.getName());
                        
                        // 检查区域编码是否存在且不为0，如果有效则添加区域名称
                        if (vo.getArea() != null && vo.getArea() != 0) {
                            Area area = AreaUtils.getArea(vo.getArea());
                            if (area != null) {
                                sb.append(" ");
                                sb.append(area.getName());
                            }
                        }
                        
                        vo.setAreaInfo(sb.toString());

                    } else {
                        // 城市地区对象获取失败，使用详细地址
                        vo.setAreaInfo(vo.getDetailAddress() != null ? vo.getDetailAddress() : "未知地区");
                    }
                }
                // 如果城市编码为空或为0，检查省份编码
                else if (vo.getProvince() != null && vo.getProvince() != 0) {
                    // 尝试获取省份地区对象
                    Area province = AreaUtils.getArea(vo.getProvince());
                    if (province != null) {
                        vo.setAreaInfo(province.getName());
                    } else {
                        // 省份地区对象获取失败，使用详细地址
                        vo.setAreaInfo(vo.getDetailAddress() != null ? vo.getDetailAddress() : "未知地区");
                    }
                }
                // 如果省市都为空，则使用详细地址
                else if (vo.getDetailAddress() != null) {
                    vo.setAreaInfo(vo.getDetailAddress());
                } else {
                    vo.setAreaInfo("未知地区");
                }
            } catch (Exception e) {
                // 如果转换异常，设置一个默认值
                vo.setAreaInfo(vo.getDetailAddress() != null ? vo.getDetailAddress() : "未知地区");
                e.printStackTrace();
            }

            // 2. 设置负责人名称
            if (vo.getOwnUserName() == null && vo.getOwnerUserId() != null) {
                // 如果名称为空但ID存在，尝试查询用户名
                try {
                    AdminUserDO adminUser = userMapper.selectById(vo.getOwnerUserId());
                    if (adminUser != null) {
                        vo.setOwnUserName(adminUser.getNickname());
                    } else {
                        vo.setOwnUserName("未知用户");
                    }
                } catch (Exception e) {
                    vo.setOwnUserName("未知用户");
                    e.printStackTrace();
                }
            }
        }

        // 创建一个新的序列化后的列表，确保所有字段被正确处理
        List<CrmCluesExportVO> exportList = new ArrayList<>(list.size());
        for (CrmCluesRespVO vo : list) {
            CrmCluesExportVO exportVO = new CrmCluesExportVO();
            
            // 基础信息
            exportVO.setId(vo.getId());
            exportVO.setName(vo.getName());
            exportVO.setMobile(vo.getMobile());
            exportVO.setTelephone(vo.getTelephone());
            exportVO.setStatus(vo.getStatus() != null ? vo.getStatus().toString() : "");
            exportVO.setCustomerId(vo.getCustomerId());
            exportVO.setChangeTime(vo.getChangeTime());
            
            // 计算出生年份：基于年龄和创建时间
            if (vo.getAge() != null && !vo.getAge().isEmpty() && vo.getCreateTime() != null) {
                try {
                    int age = Integer.parseInt(vo.getAge());
                    int createYear = vo.getCreateTime().getYear();
                    int birthYear = createYear - age;
                    exportVO.setBirthYear(String.valueOf(birthYear));
                } catch (NumberFormatException e) {
                    // 如果年龄不是有效的数字，则不设置出生年份
                    exportVO.setBirthYear("");
                }
            } else {
                exportVO.setBirthYear("");
            }
            
            // 客户属性
            exportVO.setLevel(vo.getLevel() != null ? vo.getLevel().toString() : "");
            exportVO.setIndustry(convertIndustryCodeToName(vo.getIndustry()));
            exportVO.setTags(vo.getTags());
            exportVO.setSource(vo.getSource() != null ? vo.getSource().toString() : "");
            exportVO.setRemark(vo.getRemark());
            exportVO.setOwnerName(vo.getOwnUserName());
            
            // 地址信息
            exportVO.setProvince(vo.getProvince() != null ? vo.getProvince().toString() : "");
            exportVO.setCity(vo.getCity() != null ? vo.getCity().toString() : "");
            exportVO.setArea(vo.getArea() != null ? vo.getArea().toString() : "");
            exportVO.setDetailAddress(vo.getDetailAddress());
            exportVO.setAreaInfo(vo.getAreaInfo());
            
            // 时间信息
            exportVO.setNextTime(vo.getNextTime());
            exportVO.setFollowTime(vo.getFollowTime());
            exportVO.setCollectTime(vo.getCollectTime());
            exportVO.setCreateTime(vo.getCreateTime());
            exportVO.setAssignTime(vo.getAssignTime());
            exportVO.setRegisterTime(vo.getRegisterTime());
            exportVO.setUpdateTime(vo.getUpdateTime());
            
            // 跟进信息
            exportVO.setFollowStatus(vo.getFollowStatus() != null ? vo.getFollowStatus().toString() : "");
            exportVO.setFollowRecords(vo.getFollowRecords());
            
            // 联系方式
            exportVO.setQq(vo.getQq());
            exportVO.setWechat(vo.getWechat());
            exportVO.setChannelSource(vo.getChannelSource());
            
            // 个人信息
            exportVO.setSex(vo.getSex());
            exportVO.setAge(vo.getAge());
            exportVO.setMarried(vo.getMarried());
            exportVO.setEducation(vo.getEducation());
            exportVO.setHeight(vo.getHeight());
            exportVO.setWeight(vo.getWeight());
            exportVO.setIncome(vo.getIncome());
            exportVO.setUserName(vo.getUserName());
            exportVO.setDealStatus(vo.getDealStatus());
            exportVO.setCluesLevel(vo.getCluesLevel());
            exportVO.setRemarks(vo.getRemarks());
            
            // 系统信息
            exportVO.setCreator(vo.getCreator());
            exportVO.setUpdater(vo.getUpdater());
            
            exportList.add(exportVO);
        }

        // 处理选中的列
        Set<String> selectedColumns = null;
        if (pageReqVO.getSelectedColumns() != null && !pageReqVO.getSelectedColumns().isEmpty()) {
            selectedColumns = new HashSet<>(Arrays.asList(pageReqVO.getSelectedColumns().split(",")));
            System.out.println("选中的导出列: " + selectedColumns);
        }

        // 使用动态导出工具类
        if (selectedColumns != null && !selectedColumns.isEmpty()) {
            DynamicExcelExportUtil.write(response, "线索数据.xls", "数据", exportList, selectedColumns, CrmCluesExportVO.class);
        } else {
            // 如果没有指定列，使用原有的导出方式
            ExcelUtils.write(response, "线索数据.xls", "数据", CrmCluesExportVO.class, exportList);
        }
    }

    @GetMapping("/public-sea/page")
    @Operation(summary = "获得公海线索分页")
    @PreAuthorize("@ss.hasPermission('crm:clues:query')")
    public CommonResult<PageResult<CrmCluesRespVO>> getPublicSeaCluesPage(@Valid CrmCluesPageReqVO pageReqVO) {
        // 调用专门的公海线索查询方法，直接查询负责人为空的线索
        return success(cluesService.getPublicSeaCluesPage(pageReqVO));
    }

    /**
     * 将行业数字代码转换为中文名称
     * 
     * @param industryCode 行业代码
     * @return 行业中文名称
     */
    private String convertIndustryCodeToName(Integer industryCode) {
        if (industryCode == null) {
            return "";
        }
        
        switch (industryCode) {
            case 0: return "未选择";
            case 1: return "金融";
            case 2: return "教育培训";
            case 3: return "医疗健康";
            case 4: return "房地产";
            case 5: return "制造业";
            case 6: return "服务业";
            case 7: return "IT/互联网";
            default: return industryCode.toString();
        }
    }

}
